package cn.maihe.elg.operation.supports.bank.service;

import cn.maihe.elg.operation.config.CiticBankConfig;
import cn.maihe.elg.operation.model.dto.BaseReq;
import cn.maihe.elg.operation.model.dto.BaseResp;
import cn.maihe.elg.operation.supports.bank.BaseCiticBankTransService;
import cn.maihe.elg.operation.supports.bank.dto.CiticAccountDetailItem;
import cn.maihe.elg.operation.supports.bank.dto.CiticAccountDetailReqDTO;
import cn.maihe.elg.operation.supports.bank.dto.CiticAccountDetailRespDTO;
import cn.maihe.elg.operation.utils.ElgLogger;
import cn.maihe.elg.operation.utils.IdGenerate;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Date;

import cn.maihe.elg.operation.model.enums.AcceptOrderStatus;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.SpdBankNotice;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.SpdBankNoticeService;
import cn.maihe.framework.starter.mybatis.mapper.PlusEntityWrapper;
import org.springframework.transaction.annotation.Transactional;

/**
 * @description: 中信银行账户明细服务
 */
@Service
@Slf4j
public class CiticBankAccountDetailService extends BaseCiticBankTransService<BaseReq, BaseResp> {

    @Resource
    private CiticBankConfig citicBankConfig;

    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;

    @Resource
    private SpdBankNoticeService spdBankNoticeService;

    @Resource
    private CiticBankMockService citicBankMockService;

    /**
     * 是否启用Mock模式（用于测试）
     * -- GETTER --
     *  检查是否处于Mock模式

     */
    @Getter
    private boolean mockMode = false;

    /**
     * 查询当日流水
     */
    public CiticAccountDetailRespDTO queryFullTransactionsByDate(String startDate, String endDate) {
        if (mockMode) {
            ElgLogger.info(log, l -> l.info("使用Mock模式查询账户明细，日期: {} - {}", startDate, endDate));
            return citicBankMockService.generateMockAccountDetailResponse();
        }
        List<CiticAccountDetailItem> allDetails = new ArrayList<>();
        CiticAccountDetailRespDTO firstPageResponse = null;
        int startRecord = 1;
        final int pageSize = 20;

        while (true) {
            CiticAccountDetailRespDTO currentPageResponse = queryAccountDetailsByPage(startDate, endDate, null, null, startRecord, pageSize);

            if (currentPageResponse == null || !"AAAAAAA".equals(currentPageResponse.getStatus())) {
                if (firstPageResponse == null) return currentPageResponse;
                ElgLogger.warn(log, l -> l.warn("分页查询中断，可能因网络或银行端问题。已获取 {} 条记录。", allDetails.size()));
                break;
            }

            if (firstPageResponse == null) {
                firstPageResponse = currentPageResponse;
            }
            // 没有更多记录
            if (currentPageResponse.getUserDataList() == null || currentPageResponse.getUserDataList().isEmpty()) {
                break;
            }

            allDetails.addAll(currentPageResponse.getUserDataList());
            // 已获取所有记录
            if (allDetails.size() >= currentPageResponse.getTotalRecords()) {
                break;
            }
            startRecord += currentPageResponse.getReturnRecords();
        }

        if (firstPageResponse != null) {
            firstPageResponse.setUserDataList(allDetails);
            firstPageResponse.setReturnRecords(allDetails.size());
        }

        return firstPageResponse;
    }
    public CiticAccountDetailRespDTO queryAccountDetailsByPage(String startDate, String endDate, BigDecimal lowAmount, BigDecimal upAmount, Integer startRecord, Integer pageNumber) {
        if (mockMode && (lowAmount == null && upAmount == null)) {
            return citicBankMockService.generateMockAccountDetailResponse();
        } else if(mockMode){
            return citicBankMockService.generateMockAccountDetailResponseByAmount(lowAmount,upAmount);
        }

        CiticAccountDetailReqDTO req = new CiticAccountDetailReqDTO();
        req.setUserName(citicBankConfig.getUserName());
        req.setAccountNo(citicBankConfig.getAccountNo());
        req.setStartDate(startDate);
        req.setEndDate(endDate);
        req.setLowAmount(lowAmount);
        req.setUpAmount(upAmount);
        req.setStartRecord(String.format("%04d", startRecord));
        req.setPageNumber(pageNumber);
        req.setControlFlag("2");

        return sendCiticAccountDetailQuery(req);
    }
    /**
     * 启用Mock模式
     */
    public void enableMockMode() {
        this.mockMode = true;
        ElgLogger.info(log, l -> l.info("中信银行服务已启用Mock模式"));
    }

    /**
     * 禁用Mock模式
     */
    public void disableMockMode() {
        this.mockMode = false;
        ElgLogger.info(log, l -> l.info("中信银行服务已禁用Mock模式"));
    }

    //统一的数据处理入口
    public void processAccountDetails(CiticAccountDetailRespDTO response) {
        if (response == null || response.getUserDataList() == null || response.getUserDataList().isEmpty()) {
            ElgLogger.info(log, l -> l.info("账户明细列表为空，无需处理。"));
            return;
        }

        List<CiticAccountDetailItem> details = response.getUserDataList();
        ElgLogger.info(log, l -> l.info("开始处理账户明细数据，共 {} 条记录", details.size()));

        for (CiticAccountDetailItem detail : details) {
            if (detail == null) continue;
            try {
                processSingleTransaction(detail, response);
            } catch (Exception e) {
                ElgLogger.error(log, l -> l.error("处理单笔交易明细异常: {}", e.getMessage(), e));
            }
        }
    }


    private void processSingleTransaction(CiticAccountDetailItem detail, CiticAccountDetailRespDTO respHeader) {
        if (isTransactionProcessed(detail)) {
            ElgLogger.info(log, l -> l.info("流水已存在，跳过处理。核心流水号: {}", detail.getSumTranNo()));
            return;
        }

        ElgLogger.info(log, l -> l.info("发现新流水，开始处理。核心流水号: {}", detail.getSumTranNo()));
        markTransactionProcessed(detail, respHeader);
    }

    /**
     * 检查交易是否已处理过
     */
    private boolean isTransactionProcessed(CiticAccountDetailItem detail) {
        if (detail.getSumTranNo() == null || detail.getSumTranNo().isEmpty()) {
            ElgLogger.warn(log, l -> l.warn("收到的交易明细缺少核心流水号(sumTranNo)，无法进行判重。"));
            return false;
        }
        //通过核心流水号查询是否已处理
        return spdBankNoticeService.existsCoreSerNo(detail.getSumTranNo());
    }

    /**
     * 标记交易已处理
     */
    private void markTransactionProcessed(CiticAccountDetailItem detail, CiticAccountDetailRespDTO respHeader) {
        try {
            SpdBankNotice noticeToSave = buildCiticBankNotice(detail, respHeader);
            spdBankNoticeService.saveOrUpdate(noticeToSave);
            ElgLogger.info(log, l -> l.info("新流水已成功保存到数据库。核心流水号: {}", noticeToSave.getCoreSerNo()));
        } catch (Exception e) {
            ElgLogger.error(log, l -> l.error("保存新流水到数据库时发生异常！核心流水号: {}", detail.getSumTranNo(), e));
        }
    }

    /**
     * 根据银行返回的明细，构建用于存入数据库的 SpdBankNotice 实体。
     * @param detail      中信银行返回的单条交易明细
     * @param respHeader  包含账户信息的响应头部分 (CiticAccountDetailRespDTO)
     * @return 配置好的 SpdBankNotice 实体
     */
    private SpdBankNotice buildCiticBankNotice(CiticAccountDetailItem detail, CiticAccountDetailRespDTO respHeader) {
        SpdBankNotice notice = new SpdBankNotice();

        notice.setId(IdGenerate.getId());
        // 核心流水号
        String coreSerNo = detail.getSumTranNo();
        notice.setCoreSerNo(coreSerNo);
        notice.setNoticeSerNo(coreSerNo);
        notice.setDepSerNo(coreSerNo);
        //标识为中信银行流水
        notice.setNoticeType("CITIC");
        notice.setParentAcctNo(respHeader.getAccountNo());
        notice.setParentAcctName(respHeader.getAccountName());
        //交易时间
        notice.setNoticeDate(detail.getTranDate());
        notice.setNoticeTime(detail.getTranTime());
        notice.setCoreTransDate(detail.getTranDate());
        notice.setCoreTransTime(detail.getTranTime());
        notice.setTransDate(detail.getTranDate());
        notice.setTransTime(detail.getTranTime());
        //交易金额
        notice.setTransAmt(detail.getTranAmount() != null ? detail.getTranAmount().toPlainString() : "0.00");
        //对方账户信息
        notice.setAcctName(detail.getOppAccountName());
        notice.setAcctNo(detail.getOppAccountNo());
        notice.setAcctBankName(detail.getOppOpenBankName());
        //附言
        notice.setAttach(detail.getAbstractText());
        //使用备注字段存储中信银行的特有信息, 借贷标识'C'为贷(收入), 'D'为借(支出)
        notice.setRemark1("借贷标识:" + detail.getCreditDebitFlag());
        notice.setRemark2("交易后余额:" + (detail.getBalance() != null ? detail.getBalance().toPlainString() : ""));
        notice.setRemark3("原始流水号:" + detail.getOriNum());
        notice.setGmtCreate(new Date());
        notice.setGmtModified(new Date());
        notice.setZoneCode("");
        notice.setSecuNo("");
        notice.setSecuName("");
        notice.setMerchNo("");
        notice.setMerchName("");
        notice.setAcctBankNo("");
        notice.setBusiType("");
        return notice;
    }


    /**
     * 获取交易状态描述
     */
    public String getTransactionStatusDesc(String status) {
        switch (status) {
            case "AAAAAAA":
                return "交易处理成功";
            case "AAAAAAB":
                return "经办成功待审核";
            case "AAAAAAC":
                return "预约支付成功";
            case "AAAAAAD":
                return "现金管理代理收款信息查询交易专用，表示扣款方审核通过，扣款成功";
            case "AAAAAAE":
                return "已提交银行处理，需稍后使用交易状态查询交易进行查询";
            case "AAAAAAF":
                return "批次导入提交成功";
            case "BBBBBBB":
                return "批次处理部分成功";
            case "CCCCCCC":
                return "交易处理中";
            case "EEEEEEE":
                return "交易未产生，请务必使用该业务的汇总查询交易确认交易真实状态";
            case "UNKNOWN":
                return "交易状态未知";
            default:
                return "其他错误：" + status;
        }
    }
} 